import { type GeometryOptionalCoordinates, useLocationStore } from '@/store/modules/location'
import { type Geometry, GeometryType } from '@/apis/address/type'
import { type AmapKeys, useAmapKeyStore } from '@/store/modules/amapKey'
import { type R } from '@/utils/types'

/**
 * 接口获取 高德 的各项 key
 */
export const doGetAmapKey = () => {
    return new Promise<R<AmapKeys>>((resolve, reject) => {
        setTimeout(() => {
            resolve({
                code: 200,
                data: {
                    amapKey: import.meta.env.VITE_GD_MAP_KEY,
                    amapSafeCode: import.meta.env.VITE_GD_MAP_SAFECODE,
                    amapWebServiceKey: import.meta.env.VITE_GD_WEB_MAP_KEY,
                    amapAndroidKey: import.meta.env.VITE_GD_ANDROID_MAP,
                    amapIosKey: import.meta.env.VITE_GD_IOS_MAP,
                },
            })
        }, 0)
    })
}

/**
 * 逆地址解析 可选择存储 store
 * @param {Array} location location[0]:经度,[-180,180],负数表示西经。 location[1]:纬度,[-90,90],负数表示南纬
 * 文档地址: https://lbs.amap.com/api/webservice/guide/api/georegeo
 */
export const locToAddress = (location: [number, number], saveStore = true) => {
    return new Promise<GeometryOptionalCoordinates>((resolve, reject) => {
        uni.request({
            // 逆地理编码 需要web服务高德key
            url: `https://restapi.amap.com/v3/geocode/regeo?key=${useAmapKeyStore().getAmapWebServiceKey}&location=${location[0]},${location[1]}`,
            success: (res: any) => {
                const result = res.data
                if (result.status === '1' && result.infocode === '10000') {
                    useAmapKeyStore().getAmapWebServiceKey
                    let tempObj = result.regeocode
                    const area = [] as unknown as [string, string, string?]
                    if (tempObj.addressComponent.province.length) {
                        area.push(tempObj.addressComponent.province)
                    }
                    if (tempObj.addressComponent.city.length) {
                        area.push(tempObj.addressComponent.city)
                    }
                    if (tempObj.addressComponent.district.length) {
                        area.push(tempObj.addressComponent.district)
                    }
                    if (area.length < 2) {
                        area.push('')
                    }
                    const resp = {
                        location: {
                            type: GeometryType.Point,
                            coordinates: location,
                        },
                        address: tempObj.formatted_address
                            .replace(tempObj.addressComponent.province, '')
                            .replace(tempObj.addressComponent.city, '')
                            .replace(tempObj.addressComponent.district, ''),
                        area,
                    } as GeometryOptionalCoordinates
                    if (saveStore) {
                        useLocationStore().SET_ALL(resp)
                    }
                    resolve(resp)
                } else {
                    if (saveStore) {
                        useLocationStore().SET_ADDRESS('获取地址失败，点击手动设置地址')
                    }
                    reject(res)
                }
            },
            fail: (err) => {
                console.log('获取位置信息失败', err)
                if (saveStore) {
                    useLocationStore().SET_ADDRESS('获取地址失败，点击手动设置地址')
                }
                reject(err)
            },
        })
    })
}

/**
 * 高德地图 IP 定位
 * 文档地址: https://lbs.amap.com/api/webservice/guide/api/ipconfig
 */
export const ipToAddress = (ip?: string) => {
    return new Promise<Geometry>((resolve, reject) => {
        uni.request({
            url: `https://restapi.amap.com/v3/ip?key=${useAmapKeyStore().getAmapWebServiceKey}${ip ? `&ip=${ip}` : ''}`,
            success: (res: any) => {
                const result = res.data
                if (result.status === '1' && result.infocode === '10000') {
                    // 左下坐标
                    const locationLeftBottom: string[] = result.rectangle?.split(';')?.[0]?.split(',') || []
                    // 右上坐标
                    const locationRightTop: string[] = result.rectangle?.split(';')?.[1]?.split(',') || []
                    let locationCenter = [] as unknown as [number, number]
                    if (locationLeftBottom.length && locationRightTop.length) {
                        // 保留八位小数
                        locationCenter = [
                            Number(((Number(locationLeftBottom[0]) + Number(locationRightTop[0])) / 2).toFixed(8)),
                            Number(((Number(locationLeftBottom[1]) + Number(locationRightTop[1])) / 2).toFixed(8)),
                        ]
                    }
                    console.log('高德ip获取位置信息成功,城市中心坐标:', locationCenter)
                    resolve({
                        type: GeometryType.Point,
                        // 坐标只能定位到城市,所以选取城市中心点
                        coordinates: locationCenter,
                    })
                } else {
                    console.log('高德ip获取位置信息失败', res)
                    reject(res)
                }
            },
            fail: (err) => {
                console.log('高德ip获取位置信息请求失败', err)
                useLocationStore().SET_ADDRESS('获取地址失败，点击手动设置地址')
                reject(err)
            },
        })
    })
}

/**
 * 获取当前定位
 */
export const getLocation = () => {
    return new Promise<{ longitude: number; latitude: number; address?: string }>((resolve, reject) => {
        if (window?.navigator?.geolocation) {
            window.navigator.geolocation.getCurrentPosition(
                (position) => {
                    console.log('浏览器高精度定位成功:', position.coords)
                    resolve({
                        latitude: position.coords.latitude,
                        longitude: position.coords.longitude,
                    })
                },
                (error) => {
                    console.log('浏览器获取定位失败,尝试使用ip定位', error)
                    // 尝试使用高德地图ip定位
                    ipToAddress()
                        .then((res) => {
                            resolve({
                                latitude: res.coordinates[1],
                                longitude: res.coordinates[0],
                            })
                        })
                        .catch((err) => {
                            console.log('ip定位失败,彻底定位失败', err)
                            reject(err)
                        })
                },
                {
                    enableHighAccuracy: true, //是否要求高精度的地理位置信息
                    timeout: 3001, //对地理位置信息的获取操作做超时限制，如果再该事件内未获取到地理位置信息，将返回错误
                },
            )
        } else {
            // #ifdef MP-WEIXIN
            // 微信小程序获取位置信息
            uni.getLocation({
                type: 'gcj02',
                success: (lb) => {
                    console.log('小程序获取定位成功', lb)
                    resolve({
                        latitude: lb.latitude,
                        longitude: lb.longitude,
                    })
                },
                fail: (error) => {
                    console.log('小程序获取定位失败,尝试使用ip定位', error)
                    // 尝试使用高德地图ip定位
                    ipToAddress()
                        .then((res) => {
                            resolve({
                                latitude: res.coordinates[1],
                                longitude: res.coordinates[0],
                            })
                        })
                        .catch((err) => {
                            console.log('ip定位失败,彻底定位失败', err)
                            reject(err)
                        })
                },
            })
            // #endif
            // #ifndef MP-WEIXIN
            // 非小程序环境 直接尝试使用高德地图ip定位
            ipToAddress()
                .then((res) => {
                    resolve({
                        latitude: res.coordinates[1],
                        longitude: res.coordinates[0],
                    })
                })
                .catch((err) => {
                    console.log('ip定位失败,彻底定位失败', err)
                    reject(err)
                })
            // #endif
        }
    })
}
